package com.laulkar.services;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParserException;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import com.laulkar.Constants;
import com.laulkar.R;
import com.laulkar.activities.SubwayList;
import com.laulkar.dataproviders.Alarm;
import com.laulkar.dataproviders.AlarmDbAdapter;
import com.laulkar.dataproviders.DataProvider;
import com.laulkar.dataproviders.MtaStatus;
import com.laulkar.dataproviders.Subway;
import com.laulkar.dataproviders.SubwayDbAdapter;


public class MessengerService extends Service {
    MtaStatus status;
	/** For showing and hiding our notification. */
	NotificationManager mNM;
	/** Keeps track of all current registered clients. */
	ArrayList<Messenger> mClients = new ArrayList<Messenger>();
	/** Holds last value set by a client. */
	int mValue = 0;

	/**
	 * Command to the service to register a client, receiving callbacks
	 * from the service.  The Message's replyTo field must be a Messenger of
	 * the client where callbacks should be sent.
	 */
	public static final int MSG_REGISTER_CLIENT = 1;

	/**
	 * Command to the service to unregister a client, ot stop receiving callbacks
	 * from the service.  The Message's replyTo field must be a Messenger of
	 * the client as previously given with MSG_REGISTER_CLIENT.
	 */
	public static final int MSG_UNREGISTER_CLIENT = 2;

	/**
	 * Command to service to set a new value.  This can be sent to the
	 * service to supply a new value, and will be sent by the service to
	 * any registered clients with the new value.
	 */
	public static final int MSG_GET_STATUS = 3;
	
	/**
	 * Command to service to set a new value.  This can be sent to the
	 * service to supply a new value, and will be sent by the service to
	 * any registered clients with the new value.
	 */
	public static final int MSG_START_PERIODIC =4;
	
	/**
	 * Command to service to set a new value.  This can be sent to the
	 * service to supply a new value, and will be sent by the service to
	 * any registered clients with the new value.
	 */
	public static final int MSG_STOP_PERIODIC = 5;
	
	/**
	 * Key for subway list
	 */
	public static final String SUBWAY_LIST_KEY = "subway_list";

	/**
	 * Handler of incoming messages from clients.
	 */
	class IncomingHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				break;
			case MSG_GET_STATUS:
				informCurrentStatus();
				break;
			case MSG_START_PERIODIC:
				//startPeriodicCheck();
				break;
			case MSG_STOP_PERIODIC:
				//stopPeriodicCheck();
				break;
				
			default:
				super.handleMessage(msg);
			}
		}
	}


	public void informCurrentStatus()
	{
		
		Message m = Message.obtain(null, MSG_GET_STATUS, mValue, 0);

		Bundle b = new Bundle();
		//b.putParcelable(MessengerService.SUBWAY_LIST_KEY, new Subway());
		b.putParcelableArrayList(MessengerService.SUBWAY_LIST_KEY, status.subways);
		//b.putParcelableArray(MessengerService.SUBWAY_LIST_KEY, subway);
		m.setData(b);
		for (int i=mClients.size()-1; i>=0; i--) {
			try {
				mClients.get(i).send(m);
			} catch (RemoteException e) {
				// The client is dead.  Remove it from the list;
				// we are going through the list from back to front
				// so this is safe to do inside the loop.
				mClients.remove(i);
			}
		}
	}
	/**
	 * Target we publish for clients to send messages to IncomingHandler.
	 */
	final Messenger mMessenger = new Messenger(new IncomingHandler());
	private SubwayDbAdapter mDbHelper;


	public MtaStatus checkStatus()
	{
		
		MtaStatus status = DataProvider.getStatusCSV();
		
		for(Subway s : status.subways)
		{
			
				Subway sdb = mDbHelper.fetchSubway(s.line);
				if(sdb == null)
				{
					mDbHelper.createSubway(s.line, s.status);
				}
				else {
					mDbHelper.updateSubway(s.line, s.status);
					checkIfNotificationRequired(sdb, s.status);
				}
				
			}
		return status;
	}

	private void checkIfNotificationRequired(Subway s, String status) {
		SharedPreferences pref = getSharedPreferences(Constants.SHARED_PREF_SUBWAY, 0);
		Log.i("checkNotification", "Subway " + s.line + " status:"+ status);
		boolean informUser = pref.getBoolean(s.line, true);
		
		// If user does not subscribe to this line, return
		if(!informUser)
			return;
		
		// Do not warn if the status is same
		//if(s.status.equalsIgnoreCase(status))
		//	return;
		
		if(status.equalsIgnoreCase("delays"))
			alertUserDelays(s.line);
		
		// Service has been restored
		if(status.equalsIgnoreCase("good service") && !s.status.equalsIgnoreCase("good service"))
		{
			alertUserGoodService(s.line);
		}
			
	}
	
	
	private void alertUserGoodService(String line) {
		//In this sample, we'll use the same text for the ticker and the expanded notification
		String text = "Line " + line + " Good Service";
		// Set the icon, scrolling text and timestamp
		int id = Constants.subway_icons.get(line);
		Notification notification = new Notification(id, text,
		       System.currentTimeMillis());

		// The PendingIntent to launch our activity if the user selects this notification
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
		       new Intent(this, SubwayList.class), 0);

		// Set the info for the views that show in the notification panel.
		notification.setLatestEventInfo(this, text,
		               text, contentIntent);

		// Send the notification.
		// We use a string id because it is a unique number.  We use it later to cancel.
		mNM.notify(R.string.remote_service_connected, notification);
		
	}
	private void alertUserDelays(String line) {
		//In this sample, we'll use the same text for the ticker and the expanded notification
		String text = "Line " + line + " Delays";
		// Set the icon, scrolling text and timestamp
		int id = Constants.subway_icons.get(line);
		Notification notification = new Notification(id, text,
		       System.currentTimeMillis());

		// The PendingIntent to launch our activity if the user selects this notification
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
		       new Intent(this, SubwayList.class), 0);

		// Set the info for the views that show in the notification panel.
		notification.setLatestEventInfo(this, text ,
		               text, contentIntent);

		// Send the notification.
		// We use a string id because it is a unique number.  We use it later to cancel.
		mNM.notify(R.string.remote_service_connected, notification);
		
	}
	
	
	/*
	public void startPeriodicCheck()
	{
		 long firstTime = SystemClock.elapsedRealtime();

         // Schedule the alarm!
         AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
         am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                         firstTime, 30*1000, mAlarmSender);

         // Tell the user about what we did.
         //Toast.makeText(AlarmService.this, R.string.repeating_scheduled,
         //        Toast.LENGTH_LONG).show();
	}
	
	public void stopPeriodicCheck()
	{
		
	}
	*/
	public MtaStatus getStatus()
	{
		Toast.makeText(this, R.string.remote_service_connected, Toast.LENGTH_SHORT).show();
		//URL url = new URL(eText.getText().toString());
		MtaStatus status = null;
		try {
			status = DataProvider.parseStatus(getResources());
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		//TODO Check for settings and notifications goes here

		return status;
	}
	@Override
	public void onCreate() {
		mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

		// Display a notification about us starting.
		//status = getStatus();
		AlarmDbAdapter db = new AlarmDbAdapter(this);
		db.open();
		List<Alarm> alarms = db.checkAlarms();
		if(alarms == null)
		{
			MessengerService.this.stopSelf();
		}
		showNotification();
		mDbHelper = new SubwayDbAdapter(this);
        mDbHelper.open();
        checkStatus();
        MessengerService.this.stopSelf();
        

		  
	}

	@Override
	public void onDestroy() {
		// Cancel the persistent notification.
		//mNM.cancel(R.string.remote_service_started);

		// Tell the user we stopped.
		Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
		
		mDbHelper.close();
	}

	/**
	 * When binding to the service, we return an interface to our messenger
	 * for sending messages to the service.
	 */
	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}

	/**
	 * Show a notification while this service is running.
	 */
	private void showNotification() {
		Toast.makeText(this, R.string.remote_service_connected, Toast.LENGTH_SHORT).show();
		Log.i("service**", "Doing some work");

	}
}